﻿using System;
using System.Collections.Generic;
using Gp.Scripts.Core;
using Gp.Scripts.Util;
using UnityEngine;

namespace Gp.Scripts.Core {
    public class UnitCostCom {
        public const int MaxMagicPoint = 5; 

        private readonly Dictionary<CostField, IntValue> _dic = new();

        private readonly BaseUnit _unit;


        public int this[CostField type] {
            get => _dic[type].Value;
            set => _dic[type].Value = value;
        }  
        
        
        public UnitCostCom(BaseUnit unit) {
            foreach (CostField x in Enum.GetValues(typeof(CostField))) {
                _dic[x] = new IntValue();
            }
            _unit = unit;
        }

        public void OnBattleStart() {
            // // 更新动作
            _dic[CostField.ActionTime] = new IntValue(600);
            
            IntValue maxHealth = _unit.ComStat.GetValueWrapper(StatField.MaxHealth);
            // 设置最大生命
            _dic[CostField.Health].SetMaxRangeFunc(() => maxHealth.Value);
            // 将生命值调为最大值（或从存档中获取）
            _dic[CostField.Health].ToMax();
            
            // 计算士气 ()
            // _dic[CostField.Morale].MaxRange = Global.Get<BattleSystem>().RulesModel.BasicRuleConfig.moraleRate * 5;
            // 士气最小值
            _dic[CostField.Morale].MinRange = BattleLogic.CalMinMorale(_unit);
            // 将“士气”设为最大值
            _dic[CostField.Morale].ToMax();
        }


        public void OnSmallTurnStart() {
            Recover(CostField.ActionTime, 2);
            Recover(CostField.ShiftPoint, 2);
        }


        public void OnTurnEnd() {
            Recover(CostField.Reaction, 2);
        }
        
        
        public void OnTurnStart() {
        }


        #region CURD

        public bool CheckResource(ResourceCost cost) {
            return CheckResource(cost.Type, cost.Amount);
        }

        /// <summary>
        /// 检查是否由足够资源
        /// </summary>
        /// <param name="type"></param>
        /// <param name="amount"></param>
        /// <returns></returns>
        public bool CheckResource(CostField type, int amount = 1) {
            return _dic[type].Value >= amount;
        }

        /// <summary>
        /// 获取资源
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public int GetResource(CostField type) {
            return _dic[type].Value;
        }

        public IntValue GetResourceWrapper(CostField type) => _dic[type];
        
        
        /// <summary>
        /// 获得某种资源的最小值。如果未设置，返回 int.MinValue. <see cref="int.MinValue"/>
        /// </summary>
        public int GetMinValue(CostField type) {
            return _dic[type].MinRange;
        }

        /// <summary>
        /// 获得某种资源的最大值。如果未设置，返回int.MaxValue. <see cref="int.MaxValue"/>
        /// </summary>
        public int GetMaxValue(CostField type) {
            return _dic[type].MaxRange;
        }
        
        public void ReduceResource(ResourceCost cost) {
            // 临时功能：仅当战斗开始时才会扣除行动点
            if (Global.Get<BattleSystem>().IsBattleStart)
                ReduceResource(cost.Type, cost.Amount);
        }

        public void ReduceResource(CostField type, int amount = 1) {
            _dic[type].Value -= amount;
        }
        
        private int Clamp(CostField type, int value) {
            var min = GetMinValue(type);
            var max = GetMaxValue(type);

            return Math.Clamp(value, min, max);
        }
        
        /// <summary>
        /// 将指定资源设置为0. 无论最小值为多少
        /// </summary>
        /// <param name="type"></param>
        public void ClearResource(CostField type) {
            var v = _dic[type];
            if (v.Value > 0) v.Value = 0;
        }


        public void AddResource(CostField type, int amount) {
            _dic[type].Value += amount;
        }
        #endregion


        // 阻碍回复
        private readonly List<CostField> _blockRecover = new();
        
        private void Recover(CostField item, int amount = 1) {
            // 恢复动作、附赠动作、反应、移动力
            if (_blockRecover.Contains(item)) return;
            _dic[item].Value += amount;
            _blockRecover.Remove(item);
        }
    }
}